package cn.bone.base.auth;

import cn.bone.base.component.GlobalParam;
import cn.bone.base.exception.TokenTimeoutException;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

@Component
public class JWTFactory {

    @Resource
    private GlobalParam param;


    /**
     * 生成token
     * token中记录用户类型，用户id，用户登录时间
     */
    public String createToken(Integer userId, Integer userType,String origin){
        //记录当前登录时间
        Long loginTime = new Date().getTime();
        Algorithm algorithm = Algorithm.HMAC256(param.getJwt().getPassword());

        String token = JWT.create()
                .withClaim("userId",userId)
                .withClaim("loginTime",loginTime)
                .withClaim("userType",userType)
                .withClaim("origin",origin)
                .sign(algorithm);

        JWTInfo jwtInfo = new JWTInfo();
        jwtInfo.setLoginTime(loginTime);
        jwtInfo.setOrigin(origin);
        jwtInfo.setUserId(userId);
        jwtInfo.setUserType(userType);
        save(jwtInfo);

        return token;
    }

    //保存数据到redis中
    private void save(JWTInfo jwtInfo){
        //登录时也保存到当前线程中
        JWTInfo.set(jwtInfo);
    }

    /**
     * 验证token
     */
    public void validate(String token){
        Algorithm algorithm = Algorithm.HMAC256(param.getJwt().getPassword());
        JWTVerifier verifier = JWT.require(algorithm).build();
        verifier.verify(token);    //会抛出JWTVerificationException

    }

    /**
     * 获取JWTInfo
     */
    public JWTInfo getInfo(String token){
        DecodedJWT jwt = JWT.decode(token);
        Integer userId = jwt.getClaim("userId").asInt();
        Integer userType = jwt.getClaim("userType").asInt();
        Long loginTime = jwt.getClaim("loginTime").asLong();
        String origin = jwt.getClaim("origin").asString();
        JWTInfo info = new JWTInfo();
        info.setLoginTime(loginTime);
        info.setUserId(userId);
        info.setUserType(userType);
        info.setOrigin(origin);
        return info;
    }

    /***
     * 先验证，再获取JWTInfo
     */
    public JWTInfo validateAndGet(String token){
        Algorithm algorithm = Algorithm.HMAC256(param.getJwt().getPassword());
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT jwt = verifier.verify(token);    //会抛出JWTVerificationException
        Integer userId = jwt.getClaim("userId").asInt();
        Integer userType = jwt.getClaim("userType").asInt();
        Long loginTime = jwt.getClaim("loginTime").asLong();
        String origin = jwt.getClaim("origin").asString();

        //判断token中的时间是否超过了
        if(param.getJwt().getExpireValid()==1){
            long expireTime = param.getJwt().getExpireTime() + loginTime;
            long nowTime = new Date().getTime();
            if(expireTime<nowTime){
                throw new TokenTimeoutException();
            }
        }
        JWTInfo info = new JWTInfo();
        info.setLoginTime(loginTime);
        info.setUserId(userId);
        info.setUserType(userType);
        info.setOrigin(origin);
        return info;
    }
}
